<?php


namespace models\Business;


use models\DAO\BookingModel;
use models\DAO\MemberModel;
use models\Exception\Business\BookingException;
use models\Exception\Business\MemberException;
use models\Exception\DAO\ModelDriverException;
use models\Exception\DAO\ModelException;
use models\Exception\DAO\ModelReflectionException;
use models\Exception\DAO\ModelSqlException;
use models\Exception\Service\ServiceException;
use models\Exception\Transformer\TransformerException;
use models\Exception\Business\AlibabaproductException;
use models\Service\AlibabaproductService;
use models\Service\BookingService;
use models\Service\MemberService;
use models\Service\SystemService;
use Task\client;
use Yaf\Registry;
use youliPhpLib\Common\StringOperation;

class Booking
{
    /**
     * @param array $parameters
     * @return array|mixed|null
     * @throws BookingException
     * @throws ModelDriverException
     * @throws ModelException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     * @throws ServiceException
     * @throws TransformerException
     */
    static public function editBooking($parameters = [])
    {
        try {
            if (!isset($parameters['sn']) || empty($parameters['sn']))
                throw new BookingException(BookingException::BOOKING_ID_IS_EMPTY, BookingException::BOOKING_ID_IS_EMPTY_NO);

            $update_arr = [];
            if (isset($parameters['stats']))
                $update_arr['stats'] = $parameters['stats'];
            if (isset($parameters['trade_order_sn']))
                $update_arr['trade_order_sn'] = $parameters['trade_order_sn'];
            if (isset($parameters['address_id']))
                $update_arr['address_id'] = $parameters['address_id'];
            if (isset($parameters['channel']))
                $update_arr['channel'] = $parameters['channel'];
            if (isset($parameters['num']))
                $update_arr['num'] = $parameters['num'];
            if (isset($parameters['amount']))
                $update_arr['price'] = $parameters['amount'];
            if (isset($parameters['fee']))
                $update_arr['fee'] = $parameters['fee'];

            if (isset($parameters['member_id']))
                $update_arr['member_id'] = $parameters['member_id'];
            if (isset($parameters['created_at']))
                $update_arr['created_at'] = $parameters['created_at'];
            if (isset($parameters['expired_at']))
                $update_arr['expired_at'] = $parameters['expired_at'];

            if (!empty($update_arr)) {
                $update_arr['updated_at'] = date('Y-m-d H:i:s', time());
                $booking                  = BookingService::getInstance()->update($update_arr, $parameters['sn']);
            } else
                $booking = BookingService::getInstance()->getOne($parameters['sn']);

            return $booking;
        } catch (BookingException $e) {
            throw $e;
        } catch (ModelDriverException $e) {
            if ($e->getCode() == ModelDriverException::DRIVER_EXCEPTION_MSG_NO)
                throw new BookingException(BookingException::BOOKING_EDIT_FAILURE, BookingException::BOOKING_EDIT_FAILURE_NO);
            throw $e;
        } catch (ModelException $e) {
            throw $e;
        } catch (ModelReflectionException $e) {
            throw $e;
        } catch (ModelSqlException $e) {
            throw $e;
        } catch (ServiceException $e) {
            throw $e;
        } catch (TransformerException $e) {
            throw $e;
        }
    }

    /**
     * @param $sn
     * @return array|mixed|null
     * @throws BookingException
     * @throws ModelDriverException
     * @throws ModelException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     * @throws ServiceException
     * @throws TransformerException
     */
    static public function getBookingBySn($sn)
    {
        try {
            return BookingService::getInstance()->getOne($sn);
        } catch (ModelDriverException $e) {
            throw $e;
        } catch (ModelException $e) {
            if ($e->getCode() == ModelException::DATA_NOT_EXISTS_NO)
                throw new BookingException(BookingException::BOOKING_IS_NOT_EXISTS, BookingException::BOOKING_IS_NOT_EXISTS_NO);
            throw $e;
        } catch (ModelReflectionException $e) {
            throw $e;
        } catch (ModelSqlException $e) {
            throw $e;
        } catch (ServiceException $e) {
            throw $e;
        } catch (TransformerException $e) {
            throw $e;
        }
    }

    /**
     * 通过商品编号查询这个商品总共有多少条数据在booking表里
     * @param array $parameters
     * @return array
     */
    static public function getBookingListByProductId($parameters = []) {
        try {
            $count_sql = 'SELECT count(`product_id`) AS total FROM `booking`';
            $where_arr = $res = [];
            $meta = new \stdClass();
            $return_arr = ['data' => [], 'meta' => $meta];

            if (isset($parameters['product_id']))
                array_push($where_arr, '`product_id` = "' . $parameters['product_id'] . '"');

            if (isset($parameters['stats'])) {
                if (is_array($parameters['stats']))
                    array_push($where_arr, '`stats` in ("' . implode('", "', $parameters['stats']) . '")');
                else
                    array_push($where_arr, '`stats` = "' . $parameters['stats'] . '"');
            }

            if (isset($parameters['start_created_at'])) {
                $system = System::getSystemInfo(1);
                $coupon_expire = $system['coupon_expire'];
                array_push($where_arr, ' `created_at` >= "' . date('Y-m-d H:i:s', time() - $coupon_expire) . '"');
//                array_push($where_arr, ' `created_at` >= "2020-06-22"');

            }

            if (!empty($where_arr))
                $count_sql = "SELECT count(`product_id`) AS total FROM `booking` WHERE " . implode(' AND ', $where_arr);
            $count = BookingModel::getInstance()->query($count_sql);
            $total = count($count) >= 1 ? $count[0]['total'] : ($count_sql[0]['total'] > 0 ? 1 : 0);

            if ($total > 0) {
                $system = System::getSystemInfo(1);
                $meta->total_pages = ceil($total / $parameters['page_size']);
                $meta->current_page = $parameters['page'];
                $meta->per_page = $parameters['page_size'];
                $meta->total = $total;
                $meta->count = $meta->total_page <= 1 ? $meta->total : (
                    $meta->current_page != $meta->total_page ? $meta->per_page : $meta->total - ($meta->current_page - 1) * $meta->per_page);
                $start_pos = ($meta->current_page - 1 > 0 ? $meta->current_page - 1 : 0) * $meta->per_page;
                $end_pos = $meta->per_page;
                $sql = "SELECT `product_id`, count(`member_id`) as members, min(`created_at`) as expired_at FROM `booking` WHERE " . implode(' AND ', $where_arr) .
                    ' GROUP BY `product_id` LIMIT ' . $start_pos . ', ' . $end_pos;
                $return_arr['data'] = BookingModel::getInstance()->query($sql);
                foreach ($return_arr['data'] as $idx => $product) {
                    $return_arr['data'][$idx]['expired_at'] = date("Y-m-d H:i:s", strtotime($product['expired_at']) + $system['coupon_expire']);
                }
            }

            $return_arr = AlibabaProduct::getProductByModules($return_arr);

            return $return_arr;

        } catch (\Exception $e) {
            throw new BookingException(BookingException::BOOKING_IS_NOT_EXISTS, BookingException::BOOKING_IS_NOT_EXISTS_NO);
        }
    }

    /**
     * 获取支付订单信息
     * @param array $parameters
     * @return array|mixed
     * @throws BookingException
     * @throws ModelDriverException
     * @throws ModelException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     * @throws ServiceException
     * @throws TransformerException
     */
    static public function getBookingList($parameters = [])
    {
        try {
            $rules = $condition = [];
            $coupon_expire = false;
            if (isset($parameters['member_id']))
                array_push($rules, ['field' => 'member_id', 'op' => 'eq', 'data' => $parameters['member_id']]);

            if (isset($parameters['sn']))
                array_push($rules, ['field' => 'sn', 'op' => 'in', 'data' => $parameters['sn']]);
            if (isset($parameters['trade_order_sn']))
                array_push($rules, ['field' => 'trade_order_sn', 'op' => 'eq', 'data' => $parameters['trade_order_sn']]);
            if (isset($parameters['stats'])) {
                if (is_array($parameters['stats'])) {
                    array_push($rules, ['field' => 'stats', 'op' => 'in', 'data' => implode(',', $parameters['stats'])]);
                } else
                    array_push($rules, ['field' => 'stats', 'op' => 'eq', 'data' => $parameters['stats']]);
            }

            if (isset($parameters['start_expired_at']))
                array_push($rules, ['field' => 'expired_at', 'op' => 'ge', 'data' => $parameters['start_expired_at']]);
            if (isset($parameters['end_expired_at']))
                array_push($rules, ['field' => 'expired_at', 'op' => 'le', 'data' => $parameters['end_expired_at']]);
            if (isset($parameters['product_id']))
                array_push($rules, ['field' => 'product_id', 'op' => 'eq', 'data' => $parameters['product_id']]);
            if (isset($parameters['start_created_at'])) {
                $system = System::getSystemInfo(1);
                $coupon_expire = $system['coupon_expire'];
                array_push($rules, ['field' => 'updated_at'/*'created_at'*/, 'op' => 'ge', 'data' =>
                    date('Y-m-d H:i:s', time() - $coupon_expire)]);
            }

            $condition = ['groupOp' => 'AND', 'rules' => $rules];

            $booking = BookingService::getInstance()->getList(isset($parameters['page']) ? $parameters['page'] : 1,
                isset($parameters['page_size']) ? $parameters['page_size'] : 10,
                isset($parameters['sort']) ? $parameters['sort'] : 'desc',
                isset($parameters['order']) ? $parameters['order'] : 'created_at',
                $condition
            );
            //计算总数量nums
            foreach ($booking['data'] as $key=>$value){
               $booking['data'][$key]['nums'] = array_sum(explode(',', $value['num']));
               if ($coupon_expire !== false)
                   $booking['data'][$key]['expired_at'] = date("Y-m-d H:i:s", strtotime($value['updated_at']) + $coupon_expire);
            }
            $booking = AlibabaProduct::getProductByModules($booking);

            return $booking;

        } catch (ModelDriverException $e) {
            throw $e;
        } catch (ModelException $e) {
            if ($e->getCode() == ModelException::DATA_NOT_EXISTS_NO)
                throw new BookingException(BookingException::BOOKING_IS_NOT_EXISTS, BookingException::BOOKING_IS_NOT_EXISTS_NO);
            throw $e;
        } catch (ModelReflectionException $e) {
            throw $e;
        } catch (ModelSqlException $e) {
            throw $e;
        } catch (TransformerException $e) {
            throw $e;
        }

    }

    /**
     * @param array $parameters
     * @return array
     * @throws BookingException
     * @throws ModelDriverException
     * @throws ModelException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     * @throws TransformerException
     */
    static public function createBooking($parameters = [])
    {
        try {
            // $sn = "", $trade_order_sn = "",
            // $member_id = 0, $product_id = "", $sku_id = "",
            // $address_id = 0, $num = 0, $price = 0.00, $stats = 0, $channel = 0,
            // $created_at = "", $expired_at = "", $refund_at = "", $return_at = ""
            $booking = BookingService::getInstance()->create($parameters['sn'], 0,
                $parameters['member_id'], $parameters['product_id'], $parameters['sku_id'],
                $parameters['address_id'], $parameters['num'], $parameters['amount'],
                isset($parameters['fee']) ? $parameters['fee'] : 0.00, isset($parameters['stats']) ? $parameters['stats'] : 0, $parameters['channel'],
                isset($parameters['created_at']) ? $parameters['created_at'] : date('Y-m-d H:i:s', time()),
                isset($parameters['expired_at']) ? $parameters['expired_at'] : date('Y-m-d H:i:s', time() + 15 * 60),
                '0000-00-00 00:00:00', '0000-00-00 00:00:00');

            // 调用支付接口
            // 支付宝
            if ($booking['channel'] == 0) {

            }
            // 微信
            else if ($booking['channel'] == 1) {

            }

            return $booking;
        } catch (ModelDriverException $e) {
            if ($e->getCode() == ModelDriverException::DRIVER_EXCEPTION_MSG_NO)
                throw new BookingException(BookingException::BOOKING_CREATE_FAILURE, BookingException::BOOKING_CREATE_FAILURE_NO);
            throw $e;
        } catch (ModelException $e) {
            throw $e;
        } catch (ModelReflectionException $e) {
            throw $e;
        } catch (ModelSqlException $e) {
            throw $e;
        } catch (TransformerException $e) {
            throw $e;
        }
    }

    /**
     * 处理异步回调
     * @param $booking_sn
     * @param $trade_order_sn
     * @param $stats
     * @return string
     * @throws BookingException
     * @throws ModelDriverException
     * @throws ModelException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     * @throws ServiceException
     * @throws TransformerException
     * @throws \models\Exception\Business\MemberException
     */
    static public function handlerNotifyByBookingSn($booking_sn, $trade_order_sn, $stats) {
        // 根据接口返回的订单编号查找booking表
        $booking = self::getBookingBySn($booking_sn);
        if (empty($booking))
            throw new BookingException(BookingException::BOOKING_IS_NOT_EXISTS, BookingException::BOOKING_IS_NOT_EXISTS_NO);

        // 修改booking的sql语句 修改会员信息的sql 修改阿里巴巴产品的sql
        $update_booking_sql = $update_member_balance_sql = $update_alibaba_product_sql = $insert_turnover_sql = '';
        // booking待修改字段数组
        $update_booking_arr = [];
        array_push($update_booking_arr, '`trade_order_sn` = "' . $trade_order_sn . '"');
        array_push($update_booking_arr, '`stats` = "' . (int)$stats . '"');

        // alibabaproduct带修改字段数组
        $update_alibaba_product_arr = [];
        array_push($update_alibaba_product_arr, '`platform_sales` = `platform_sales` + ' . array_sum(explode(',', $booking['num'])));
        array_push($update_alibaba_product_arr, '`sales_in_30_days` = `sales_in_30_days` + ' . array_sum(explode(',', $booking['num'])));

        /*// 三方支付订单号不为空或订单状态不为未支付
        if ($booking['trade_order_sn'] != 0 || $booking['stats'] != 0)
            throw new BookingException(BookingException::INVALID_BOOKING_STATS, BookingException::INVALID_BOOKING_STATS_NO);
        $booking = self::editBooking(['sn' => $booking_sn, 'stats' => (int)$stats, 'trade_order_sn' => $trade_order_sn]);*/

        $coupon = new Coupon($booking['product_id'], $booking['num'], $booking['member_id'], $booking['sku_id']);
        // 删除"product:wait4pay:product_id"队列
        // 插入"product:paid:拼团结束时间的时间戳"队列
        list($refund, $system_deadline_time) = $coupon->setPaidList($booking_sn);
        $coupon->closeRedis();

        $insert_turnover_arr = [];
        // 收到异步回调时已经超时，此时将金额退回余额，并告知用户拼团失败，支付金额已退回余额
        if ($refund === true && $system_deadline_time == 0) {
            $update_member_balance_sql = "UPDATE `member` SET `balance` = `balance` + " . $booking['price'] . " WHERE `id` = '" . $booking['member_id'] . "'";
            // 收到异步回调时已经超时，所以该订单的stats为3(已退款)
            array_push($update_booking_arr, '`stats` = "3"');
            // 收到异步回调时已经超时，所以该订单的refunded_at为当前时间(退款时间)
            array_push($update_booking_arr, '`refund_at` = "' . date('Y-m-d H:i:s') . '"');
            // 资金流水记录
            $member_info = Member::getMemberInfoById($booking['member_id']);
            array_push($insert_turnover_arr, ['type' => 4, 'member_id' => $booking['member_id'], 'currency' => $member_info['balance'],
                'amount' => $booking['price'], 'remain' => $member_info['balance'] + $booking['price'], 'stats' => 1,
                'remark' => '支付到账时拼团已结束，退回购买金额至余额账户', 'created_at' => date('Y-m-d H:i:s', time()),
                'updated_at' => date('Y-m-d H:i:s', time())]);
        } else {
            // 写入after
            $client = new client();
            try {
                $product_id = $booking['product_id'];
                $num = $booking['num'];
                $client->connect();
                $client->couponAlgorithm($product_id, $num, $system_deadline_time);
            } catch (\Exception $e) {
                Registry::get('notify_log')->info("异步任务失败: " . $e->getMessage());
            } finally {
                $client->close();
            }
        }

        // booking待修改字段数据不为空时，生成修改booking的sql语句
        if (!empty($update_booking_arr))
            $update_booking_sql = "UPDATE `booking` SET " . implode(',', $update_booking_arr) .  " WHERE `sn` = '" . $booking_sn . "'";

        // 修改商品的真实销量与30天内销量
        if (!empty($update_alibaba_product_arr))
            $update_alibaba_product_sql = "UPDATE `alibabaproduct` SET " . implode(',', $update_alibaba_product_arr) . " WHERE `product_id` = '" . $booking['product_id'] . "'";

        if (!empty($insert_turnover_arr))
            $insert_turnover_sql = "INSERT INTO `turnover` (`" . implode('`, `', array_keys($insert_turnover_arr)) .
                "`) VALUE ('" . array_values($insert_turnover_arr) . "')";

        $model = BookingModel::getInstance();
        $conn = $model->getConn();
        $conn->beginTransaction();
        try {
            // 修改booking
            if (!empty($update_booking_sql)) {
                $conn->executeQuery($update_booking_sql);
                Registry::get('notify_log')->info("修改booking的sql: " . $update_booking_sql);
            }

            // 修改member
            if (!empty($update_member_balance_sql)) {
                $conn->executeQuery($update_member_balance_sql);
                Registry::get('notify_log')->info("收到异步回调时已经超时，退还支付金额到指定用户的余额中的sql: " . $update_member_balance_sql);
            }

            // 新增余额流水
            if (!empty($insert_turnover_sql)) {
                $conn->executeQuery($insert_turnover_sql);
                Registry::get('notify_log')->info("新增流水记录sql: " . $insert_turnover_sql);
            }

            // 修改商品30天内销量与平台总销量
            if (!empty($update_alibaba_product_sql)) {
                $conn->executeQuery($update_alibaba_product_sql);
                Registry::get('notify_log')->info("修改alibabaproduct的sql: " . $update_alibaba_product_sql);
            }

            $conn->commit();
            $success = 'success';
        } catch (\Exception $e) {
            $conn->rollback();
            $success = 'error';
        } finally {
            return $success;
        }
    }

    /**
     * 判断是否创建/删除机器人拼团信息
     * @param string $product_id 商品编号
     * @param bool $gen_coupon 是否生成机器人拼团信息
     * @throws BookingException
     */
    static public function chkMachineCoupon($product_id, $gen_coupon = true) {
        try {
            $booking_info = BookingService::getInstance()->getOne(['groupOp' => 'AND', 'rules' => [
                ['field' => 'product_id', 'op' => 'eq', 'data' => $product_id],
                ['field' => 'stats', 'op' => 'eq', 'data' => '20']
            ]]);
            // 机器人拼团信息不存在，且生成拼团信息
            if (empty($booking_info) && $gen_coupon === true)
                throw new BookingException(BookingException::BOOKING_NOT_EXISTS, BookingException::BOOKING_NOT_EXISTS_NO);
            // 机器人拼团信息存在，且不生成拼团信息
            else if (!empty($booking_info) && $gen_coupon === false)
                BookingService::getInstance()->delete($booking_info['sn']);
        } catch (\Exception $e) {
            if ($e->getCode() != BookingException::BOOKING_NOT_EXISTS_NO)
                throw $e;
            else {
                $product_info = ['data' => [['product_id' => $product_id]]];
                $product_info = AlibabaSku::getSkuByModules($product_info);
                $product_info = $product_info['data'][0];

                if (isset($product_info['sku'])) {
                    $sku = $product_info['sku'][array_rand($product_info['sku'])];
                    $sku_id = $sku['sku_id'];
                    try {
                        // 生成拼团信息
                        self::handlerJqBooking($product_id, $sku_id);
                    } catch (\Exception $e) {
                        throw $e;
                    }
                } else
                    throw new BookingException(BookingException::BOOKING_CREATE_FAILURE, BookingException::BOOKING_CREATE_FAILURE_NO);
            }
        }

    }

    /**
     * 回调重复发起机器拼单
     * @param $product_id
     * @param $time
     * @param $expire
     * @return bool
     */
    static public function handlerMachineBookingByProductId($product_id, $time = '', $expire = ''){
        try {

            $booking = BookingService::getInstance()->getOne(['groupOp' => 'AND', 'rules' => [
                ['field' => 'product_id', 'op' => 'eq', 'data' => $product_id],
                ['field' => 'stats', 'op' => 'eq', 'data' => '20']
            ]]);
            //Registry::get('coupon_log')->debug(__METHOD__ . 'booking的数据:' . json_encode($booking));
            if (empty($booking))
                throw new BookingException(BookingException::BOOKING_NOT_EXISTS, BookingException::BOOKING_NOT_EXISTS_NO);

            // 校验商品状态是否合法
            $product = AlibabaproductService::getInstance()->getOne(['groupOp' => 'AND', 'rules' => [
                ['field' => 'product_id', 'op' => 'eq', 'data' => $booking['product_id']],
                ['field' => 'stats', 'op' => 'eq', 'data' => 1]
            ]]);
            if (empty($product))
                throw new AlibabaproductException("商品已下架，不再发起自动拼单", 400);

            $member_list = MemberService::getInstance()->getList(1, 999, 'desc', 'id', ['groupOp' => 'AND', 'rules' => [
                ['field' => 'id', 'op' => 'ne', 'data' => $booking['member_id']],
                ['field' => 'stats', 'op' => 'eq', 'data' => 9]
            ]]);
            //Registry::get('coupon_log')->debug(__METHOD__ . '机器人会员的数据:' . json_encode($member_list));
            if (empty($member_list))
                throw new BookingException(MemberException::MACHINE_NOT_EXISTS, MemberException::MEMBER_IS_NOT_EXISTS_NO);

            $member_id = $member_list['data'][array_rand($member_list['data'])]['id'];
            //Registry::get('coupon_log')->debug(__METHOD__ . '参与拼团(' . $product_id . ')的机器人编号:' . $member_id);

            $system = System::getSystemInfo(1);
            $coupon_expire = $system['coupon_expire'];

            $data = [
                'created_at' => empty($time) ? date('Y-m-d H:i:s', time()) : $time,
                'expired_at' => empty($expire) ? date('Y-m-d H:i:s', time() + $coupon_expire) : $expire,
                'updated_at' => date('Y-m-d H:i:s', time()),
                'member_id' => $member_id,
            ];
            //Registry::get('coupon_log')->debug(__METHOD__ . '修改booking的参数:' . json_encode($data));
            BookingService::getInstance()->update($data, $booking['sn']);

            // 写入after
            $client = new client();
            try {
                $client->connect();
                $client->updateJqBooking($product_id, $coupon_expire);
            } catch (\Exception $e) {
                Registry::get('coupon_log')->info("机器拼单异步任务失败: " . $e->getMessage());
            } finally {
                $client->close();
            }

            return true;

        } catch (\Exception $e) {
            Registry::get('coupon_log')->err(__METHOD__ . '异常: ' . $e->getMessage());
        }
    }

    /**
     * 创建机器拼单记录
     * @param $product_id
     * @param $sku_id
     * @throws BookingException
     * @throws ModelException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     * @throws ServiceException
     * @throws TransformerException
     */
    static public function handlerJqBooking($product_id, $sku_id){
        try {
            //创建机器拼团
            $members = MemberModel::getInstance()->query("SELECT `id` FROM `member` WHERE `stats` =9 ");
            $memid= array_rand($members,1);

            $system = System::getSystemInfo(1);
            $coupon_expire = $system['coupon_expire'];
            $booking_data = [
                // 付款信息订单号
                'sn' => StringOperation::genOrderSn(),
                // 随机获取会员编号
                'member_id' => $members[$memid]['id'],
                // 商品编号
                'product_id' => $product_id,
                'sku_id'=>$sku_id,
                'num'=>1,
                // 时间
                'created_at' => date('Y-m-d H:i:s', time()),
                'expired_at' => date('Y-m-d H:i:s', time() + $coupon_expire),
                // 订购信息状态 机器拼团
                'stats' => 20
            ];
            self::createBooking($booking_data);

            // 写入after
            $client = new client();
            try {
                $client->connect();
                $client->updateJqBooking($product_id,$coupon_expire);
            } catch (\Exception $e) {
                Registry::get('notify_log')->info("机器拼单异步任务失败: " . $e->getMessage());
            } finally {
                $client->close();
            }
        } catch (ModelDriverException $e) {
            throw new BookingException(BookingException::JQ_BOOKING_ARR, BookingException::JQ_BOOKING_ARR_NO);
        } catch (ModelException $e) {
            throw $e;
        } catch (ModelReflectionException $e) {
            throw $e;
        } catch (ModelSqlException $e) {
            throw $e;
        } catch (TransformerException $e) {
            throw $e;
        }
    }

}
